package com.run_java_test.jar_local_run.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.support.GenericBeanDefinition;
import org.springframework.stereotype.Service;

import java.io.File;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.HashSet;
import java.util.Set;

@Service
public class DynamicJarLoaderService {

    private final DefaultListableBeanFactory beanFactory;

    // class 的 set 集合
    private final Set<Class<?>> classesToRegister = new HashSet<>();

    // 记录的 bean 集合
    private final Set<String> registeredBeanNames = new HashSet<>();

    @Autowired
    public DynamicJarLoaderService(DefaultListableBeanFactory beanFactory) {
        this.beanFactory = beanFactory;
    }

//    public DynamicJarLoader(ApplicationContext applicationContext) {
//        this.beanFactory = (DefaultListableBeanFactory) ((AnnotationConfigApplicationContext) applicationContext).getBeanFactory();
//    }

    // 动态加载 JAR 文件
    public void loadJar(String jarPath) throws Exception {
        File jarFile = new File(jarPath);
        URL jarUrl = jarFile.toURI().toURL();

        try (URLClassLoader classLoader = new URLClassLoader(new URL[]{jarUrl}, this.getClass().getClassLoader())) {
            // 遍历 JAR 文件的所有类
            for (String className : JarUtils.getClassNamesFromJar(jarFile)) {
                Class<?> clazz = Class.forName(className, true, classLoader);
                classesToRegister.add(clazz);
            }

            // 关闭 jar 加载器
            classLoader.close();
        }
        System.out.println("遍历 JAR 文件的所有类 完成");

        // 第一步：注册所有 BeanDefinition 相当于定义bean
        for (Class<?> clazz : classesToRegister) {
            this.registerBeanDefinition(clazz);
        }
        System.out.println("注册所有 BeanDefinition 完成");

//        // 第二步：实例化所有 Bean 这个是bean进行实例化
//        for (Class<?> clazz : classesToRegister) {
//            // 这是从当前项目的类里面获取bean, 使用其他方式加载
//            beanFactory.getBean(clazz);
//        }

        // 第二步：实例化所有 Bean 这个是bean进行实例化
        for (String beanName : registeredBeanNames) {
            if (beanFactory.containsBeanDefinition(beanName)) {
                beanFactory.getBean(beanName); // 确保依赖解析完成
                System.out.println("Bean 加载: " + beanName);
            }
        }
        System.out.println("实例化所有 Bean 完成");
    }

    // 注册 BeanDefinition
    private void registerBeanDefinition(Class<?> clazz) {
        // 注册bean, 但是没有被实例化
        GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
        // 设置class
        beanDefinition.setBeanClass(clazz);
        // 单例模式
        beanDefinition.setScope(BeanDefinition.SCOPE_SINGLETON);
        // bean名称
        String beanName = Character.toLowerCase(clazz.getSimpleName().charAt(0)) + clazz.getSimpleName().substring(1);
        // 注册bean, 设置名称 设置bean定义
        beanFactory.registerBeanDefinition(beanName, beanDefinition);

        // 记录已注册的 Bean 名称
        registeredBeanNames.add(beanName);
    }

    // 卸载所有动态加载的 Bean
    public void unloadJar() {
        for (String beanName : registeredBeanNames) {
            if (beanFactory.containsBeanDefinition(beanName)) {
                // 触发 Bean 的销毁方法
                Object beanInstance = beanFactory.getSingleton(beanName);
                if (beanInstance != null) {
                    beanFactory.destroySingleton(beanName);
                }

                // 移除 BeanDefinition
                beanFactory.removeBeanDefinition(beanName);
                System.out.println("Bean 已卸载: " + beanName);
            }
        }
        // 清理缓存 确保卸载时清理元数据缓存 避免依赖解析失败
        beanFactory.clearMetadataCache(); // 清理元数据缓存
        // 清空记录
        classesToRegister.clear();
        registeredBeanNames.clear();
    }
}
